﻿/*****************************************************************//**
 * @file    FITKSetSurfPolyProvider.h
 * @brief   Set and surface poly data manager.
 *  
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2024-04-19
 *********************************************************************/

#ifndef __FITKSETSURFPOLYROVIDER_H__
#define __FITKSETSURFPOLYROVIDER_H__

#include <QObject>

#include <QHash>

 // Forward declaration
class vtkUnstructuredGrid;
class vtkDataSet;
class vtkDataObject;
class vtkTransform;

namespace Interface
{
    class FITKModelSet;

    class FITKMeshSurface;
    class FITKMeshSurfaceElement;
    class FITKMeshSurfaceNode;
    struct AbaEleSurface;

    class FITKAbaqusPart;
    class FITKAbaMeshPartVTK;
    class FITKAbstractAssInstance;
    class FITKAbaAssembly;
}

namespace AbaqusData
{
    class FITKAbaqusPart;
}

namespace Exchange
{
    /**
     * @brief   Set and surface poly data manager.
     * @author  ChengHaotian (yeguangbaozi@foxmail.com)
     * @date    2024-04-19
     */
    class FITKSetSurfPolyProvider : public QObject
    {
        Q_OBJECT

    public:
        /**
         * @brief   Get the instance of this class.[static]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        static FITKSetSurfPolyProvider* getInstance();

        /**
         * @brief   Check the given id and return if the id is a shell surface.[static]
         * @param   surfaceId: The id maybe surface
         * @param   instanceId: The instance id of the surface[default]
         * @return  Is shell surface
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-06-18
         */
        static bool IsShellSurface(int surfaceId, int instanceId = -1);

        /**
         * @brief   Check the given id and return if the id is a shell surface, and the
         *          label is not an edge.[static]
         * @param   surfaceId: The id maybe surface
         * @param   instanceId: The instance id of the surface[default]
         * @return  Is surface a none edge shell surface
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-07-11
         */
        static bool IsShellSurfaceNoneEdge(int surfaceId, int instanceId = -1);

        /**
         * @brief   Get all sub set ids by the given comp-set id.[static]
         * @param   setId: The id maybe set
         * @return  The sub set ids
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-07-18
         */
        static QList<int> GetCompSetSubSetIds(int setId);

        /**
         * @brief   Get all sub set ids by the given surface id.[static]
         * @param   surfaceId: The id maybe surface
         * @return  The sub set ids
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-07-18
         */
        static QList<int> GetSurfaceSubSetIds(int surfaceId);

        /**
         * @brief   Get the model ids array name for vtk.
         * @return  The array name[const]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-14
         */
        const char* getModelIdsArrayName();

        /**
         * @brief   Get set grid data.
         * @param   setId: The set data object id
         * @param   modelId: The set's real model id[quote]
         * @param   instanceId: The instance ID[default]
         *          ( If this set is belonged to an instance, than the instance ID mustn't be -1)
         * @return  The grid data of the set
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* getSetGridData(int setId, int& modelId, int instanceId = -1);

        /**
         * @brief   Get surface grid data.
         * @param   surfaceId: The surface data object id
         * @param   modelIds: The surface's all model ids[quote]
         * @param   instanceId: The instance ID[default]
         *          ( If this surface is belonged to an instance, than the instance ID mustn't be -1)
         * @return  The grid data of the surface
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* getSurfaceGridData(int surfaceId, QList<int>& modelIds, int instanceId = -1);

        /**
         * @brief   Delete the set grid data( if exists ).
         * @param   setId: The set data object id
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-07-18
         */
        void deleteSetGridData(int setId);

        /**
         * @brief   Delete the surface poly data( if exists ).
         * @param   surfaceId: The surface data object id
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-07-18
         */
        void deleteSurfaceGridData(int surfaceId);
      
    private:
        /**
         * @brief   Constructor.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        FITKSetSurfPolyProvider();

        /**
         * @brief   Destructor.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        ~FITKSetSurfPolyProvider();

        // For Generating Set.
        //@{
        /**
         * @brief   Generate set grid by the set data object and instance id.
         * @param   set: The set data object
         * @param   instanceId: The instance ID[default]
         *          ( If this set is belonged to an instance, than the instance ID mustn't be -1)
         * @return  The grid data of the set
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateSetGrid(Interface::FITKModelSet* set, int& modelId, int instanceId);

        /**
         * @brief   Generate dataset with the given input part data and indice of points or cells.
         * @param   part: The input part data
         * @param   type: The indice type( 1: Points, 2: Cells )
         * @param   ids: The id of points or cells( not index )
         * @return  The output dataset
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateSetDataSetWithPart(AbaqusData::FITKAbaqusPart* part, int type, const QList<int>& ids);

        /**
         * @brief   Generate dataset with the given input instance data and indice of points or cells.
         * @param   instance: The input instance data
         * @param   type: The indice type( 1: Points, 2: Cells )
         * @param   ids: The id of points or cells( not index )[quote]
         * @return  The output dataset
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateSetDataSetWithInstance(Interface::FITKAbstractAssInstance* instance, int type, const QList<int>& ids);

        /**
         * @brief   Generate dataset with the given input assembly data and indice of points or cells.
         * @param   assembly: The input assembly data
         * @param   type: The indice type( 1: Points )
         * @param   ids: The id of points or cells( not index )[quote]
         * @return  The output dataset
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateSetDataSetWithAssembly(Interface::FITKAbaAssembly* assembly, int type, const QList<int>& ids);
        //@}

        // For Generating Surface.
        /**
         * @brief   Get surface grid data.
         * @param   surface: Surface data object
         * @param   modelIds: The surface's all model ids[quote]
         * @param   instanceId: The instance ID[default]
         *          ( If this surface is belonged to an instance, than the instance ID mustn't be -1)
         * @return  The grid data of the surface
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateSurfaceGrid(Interface::FITKMeshSurface* surface, QList<int>& modelIds, int instanceId = -1);

        //@{
        /**
         * @brief   Generate an element surface actor.
         * @param   eleSurf: Element surface data object
         * @param   modelIds: The surface's all model ids[quote]
         * @param   instanceId: The instance ID[default]
         *          ( If this surface is belonged to an instance, than the instance ID mustn't be -1)
         * @return  The output dataset
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateElementSurface(Interface::FITKMeshSurfaceElement* eleSurf, QList<int>& modelIds, int instanceId = -1);

        /**
         * @brief   Generate an node surface actor.
         * @param   nodeSurf: Node surface data object
         * @param   modelIds: The surface's all model ids[quote]
         * @param   instanceId: The instance ID[default]
         *          ( If this surface is belonged to an instance, than the instance ID mustn't be -1)
         * @return  The output dataset
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        vtkUnstructuredGrid* generateNodeSurface(Interface::FITKMeshSurfaceNode* nodeSurf, QList<int>& modelIds, int instanceId = -1);

        /**
         * @brief   Copy the points from the mesh data object.
         * @param   meshData: The mesh data object
         * @param   polyData: The target mesh grid
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        void copyPoints(Interface::FITKAbaMeshPartVTK* meshData, vtkUnstructuredGrid* polyData);

        /**
         * @brief   Insert a new cell with the face data and mesh data object.
         * @param   meshData: The mesh data object
         * @param   polyData: The target mesh grid
         * @param   cellId: The cell id
         * @param   surfaceLabel: The surface index label
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        void insertNextCell(Interface::FITKAbaMeshPartVTK* meshData, vtkUnstructuredGrid* polyData, int cellId, int surfaceLabel);

        /**
         * @brief   Insert a new cell with a single point.
         * @param   meshData: The mesh data object
         * @param   polyData: The target mesh grid
         * @param   id: The index of point
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        void insertNextPointCell(Interface::FITKAbaMeshPartVTK* meshData, vtkUnstructuredGrid* polyData, int id);
        //@}

    private:
        /**
         * @brief   The model ids array name.[const]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-14
         */
        const char* c_modelIdArrayName = "__model_ids__";

        /**
         * @brief   The instance of this class.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        static FITKSetSurfPolyProvider* s_instance;

        /**
         * @brief   The set poly data hash.
         *          The first key is the set id,
         *          the second key is the model id.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        QHash<int, QHash<int, vtkUnstructuredGrid*>> m_setGridHash;

        /**
         * @brief   The surface poly data hash.
         *          The first key is the surface id,
         *          the second key is the model id.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-04-19
         */
        QHash<int, QHash<int, vtkUnstructuredGrid*>> m_surfaceGridHash;

        /**
         * @brief   The set poly data hash.
         *          The first key is the set id,
         *          the second key is the model id,
         *          the value is the model ids.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-30
         */
        QHash<int, QHash<int, int>> m_setGridModelIdsHash;

        /**
         * @brief   The surface poly data hash.
         *          The first key is the surface id,
         *          the second key is the model id,
         *          the value is the model ids.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-05-30
         */
        QHash<int, QHash<int, QList<int>>> m_surfaceGridModelIdsHash;
     
    };
}   // namespace Exchange

#endif // __FITKSETSURFPOLYROVIDER_H__
